package fsm

import (
	"encoding/json"
	"time"

	"gitee.com/hasika/gotool/generic"
)

type savedRuntimeData[State generic.Primitive] struct {
	LastState          State
	CurrentState       State
	StateLeftDuration  time.Duration
	StateTotalDuration time.Duration
}

type runtimeData[State generic.Primitive, Arg any] struct {
	lastState          State
	currentState       State
	currentStateInfo   IState[State, Arg]
	stateLeftDuration  time.Duration
	stateTotalDuration time.Duration
}

func (r *runtimeData[State, Arg]) toToSaved() *savedRuntimeData[State] {
	return &savedRuntimeData[State]{
		LastState:          r.lastState,
		CurrentState:       r.currentState,
		StateLeftDuration:  r.stateLeftDuration,
		StateTotalDuration: r.stateTotalDuration,
	}
}

func (f *FSM[State, Arg]) UnmarshalJSON(bytes []byte) error {
	data := &savedRuntimeData[State]{}
	err := json.Unmarshal(bytes, data)
	if err != nil {
		return err
	}
	f.runtimeData.lastState = data.LastState
	f.runtimeData.currentStateInfo = f.stateMap[data.CurrentState]
	f.runtimeData.stateLeftDuration = data.StateLeftDuration
	f.runtimeData.stateTotalDuration = data.StateTotalDuration
	return nil
}

func (f *FSM[State, Arg]) MarshalJSON() ([]byte, error) {
	saved := f.toToSaved()
	return json.Marshal(saved)
}
